package com.ljy.my_study.leetcode.存在重复元素III;

import java.util.HashMap;
import java.util.Map;

public class TestMain {

//    给你一个整数数组 nums 和两个整数 k 和 t 。请你判断是否存在 两个不同下标 i 和 j，使得 abs(nums[i] - nums[j]) <= t ，同时又满足 abs(i - j) <= k 。
//
//    如果存在则返回 true，不存在返回 false。
//
//             
//
//    示例 1：
//
//    输入：nums = [1,2,3,1], k = 3, t = 0
//    输出：true
//    示例 2：
//
//    输入：nums = [1,0,1,1], k = 1, t = 2
//    输出：true
//    示例 3：
//
//    输入：nums = [1,5,9,1,5,9], k = 2, t = 3
//    输出：false
//             
//
//    提示：
//
//            0 <= nums.length <= 2 * 104
//            -231 <= nums[i] <= 231 - 1
//            0 <= k <= 104
//            0 <= t <= 231 - 1
//
//    来源：力扣（LeetCode）
//    链接：https://leetcode-cn.com/problems/contains-duplicate-iii
//    著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。

    public static void main(String[] args) {
        int[] nums=new int[]{1,5,9,1,5,9};
        int k=2;
        int t=3;
//        System.out.println(new TestMain().containsNearbyAlmostDuplicate(nums,k,t));
        nums=new int[]{1,0,1,1};
        k=1;
        t=2;
//        System.out.println(new TestMain().containsNearbyAlmostDuplicate(nums,k,t));
        nums=new int[]{1,2};
        k=0;
        t=1;
        System.out.println(new TestMain().containsNearbyAlmostDuplicate(nums,k,t));
    }

//    桶算法
    public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {

        Map<Long,Long> map=new HashMap<>();
        long w=(long)t+1;
        for(int i=0;i<nums.length;i++){
            long id=getId(nums[i],w);
            if(map.containsKey(id)){
                return true;
            }
            if(map.containsKey(id-1)&&((long)nums[i]-(long)map.get(id-1))<w){
                return true;
            }
            if(map.containsKey(id+1)&&((long)map.get(id+1)-(long)nums[i])<w){
                return true;
            }
            map.put(id,(long)nums[i]);
            if(i>=k){
                map.remove(getId(nums[i-k],w));
            }
        }
        return false;
    }

    private long getId(long x,long w){
        if (x >= 0) {
            return x / w;
        }
        return (x + 1) / w - 1;
    }
}
